#include "histogram.h"

#include <QDebug>
#include <QPainter>

#include <cmath>

Histogram::Histogram(QImage* image)
{
	R = new QHash<int, int>;
	G = new QHash<int, int>;
	B = new QHash<int, int>;
	L = new QHash<int, int>;

	for(int i = 0; i < 256; i++)
	{
		R->insert(i, 0);
		G->insert(i, 0);
		B->insert(i, 0);
		L->insert(i, 0);
	}

	generate(image);
}

Histogram::~Histogram()
{
	delete R;
	delete G;
	delete B;
	delete L;
}

void Histogram::generate(QImage* image)
{
	int width  = image->width();
	int height = image->height();

	//if (image->format() == QImage::Format_Indexed8)
	//{
	//	for (int x=0; x<width; x++)
	//		for (int y=0; y<height; y++)
	//		{
	//			QRgb c = image->pixel(x, y);
	//			int l = qGray(c);

	//			L->insert(l, L->value(l) + 1);
	//		}
	//}
	//else //if (image->format() == QImage::Format_RGB32)
	//{
		for (int x=0; x<width; x++)
			for (int y=0; y<height; y++)
			{
				QRgb pixel = image->pixel(x,y);

				int r = qRed(pixel);
				int g = qGreen(pixel);
				int b = qBlue(pixel);
				int l = qGray(pixel);


				R->insert(r, R->value(r) + 1);
				G->insert(g, G->value(g) + 1);
				B->insert(b, B->value(b) + 1);
				L->insert(l, L->value(l) + 1);

			}
	//}
}

/** Returns the maximal value of the histogram in the given channel */
int Histogram::maximumValue(Channel selectedChannel = RGB)
{
	int r_max = 0;
	int g_max = 0;
	int b_max = 0;
	int l_max = 0;

	for (QHash<int, int>::const_iterator i = R->begin(); i != R->end(); i++)
	{
		if(i.value() > r_max) r_max = i.value();
	}

	for (QHash<int, int>::const_iterator i = G->begin(); i != G->end(); i++)
	{
		if(i.value() > g_max) g_max = i.value();
	}

	for (QHash<int, int>::const_iterator i = B->begin(); i != B->end(); i++)
	{
		if(i.value() > b_max) b_max = i.value();
	}

	for (QHash<int, int>::const_iterator i = L->begin(); i != L->end(); i++)
	{
		if(i.value() > l_max) l_max = i.value();
	}

	switch (selectedChannel)
	{
	case Histogram::RGB:
		return std::max((r_max), std::max(g_max, b_max));
		break;
	case Histogram::RChannel:
		return r_max;
		break;
	case Histogram::GChannel:
		return g_max;
		break;
	case Histogram::BChannel:
		return b_max;
		break;
	case Histogram::LChannel:
		return l_max;
		break;
	}

	return 0;
}


/** Returns a pointer to the given channel QHash<int, int> */
QHash<int, int>* Histogram::get(Channel channel = LChannel)
{
	if (channel==LChannel) return L;
	if (channel==RChannel) return R;
	if (channel==GChannel) return G;
	if (channel==BChannel) return B;

	return 0;
}

/**
*  Returns a 255 by 100 QImage containing a Histogram for the given channel.
*  The background is transparent (Alpha 0, RGB=255) */
QImage Histogram::getImage(Channel channel = LChannel, QBrush pen = Qt::gray)
{
	// Create blank QImage and fill it with transparent background:
	QImage histImage(255, 100, QImage::Format_ARGB32);
	histImage.fill(0);
	QPainter painter(&histImage);
	painter.setBrush(Qt::transparent); 
	painter.setPen(Qt::transparent);
	painter.drawRect(0,0,255,100);

	// Calculate the aspect ratio using the maximal value of the color histograms
	int maximum = maximumValue(RGB); //(channel == LChannel ? maximumValue(LChannel) :  maximumValue(RGB));
	float ratio = 100.0/float(maximum);

	// Preparing the painter:
	painter.setBrush(pen);
	painter.setPen(pen.color());

	int h;
	// Draw histogram
	QHash<int, int>* hist = get(channel);
	QHash<int, int>::const_iterator cit = hist->begin();

	while (cit != hist->end())
	{
		h = 100 - floor(ratio*cit.value());
		painter.drawLine(cit.key(), h, cit.key(), 100);
		++cit;
	}

	return histImage;
}
